#pragma once
#include "DataStructure/Input/Solver/SubCase.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/Database/DatabaseFactory.h"
#include "DBManager/IService/Input/Element/IElementService.h"
#include "DBManager/IService/Input/Property/IPRODService.h"
#include "DBManager/IService/Input/Subcase/ISubcaseService.h"

using SG::DataStructure::FEM::DOFDirections;
using SG::DataStructure::FEM::SubCase;
using namespace SG::DBManager;
using namespace SG::DataStructure::FEM;

/// 杆桁架模型数据
class Link_ElevenEleRigid_Frame
{
  public:
    Link_ElevenEleRigid_Frame ()
        : m_dbServiceFactory (std::make_shared<DBServiceFactory> (*DataBaseFactory::GetDataBase (DataBaseFactory::HDF5, ".", "test.h5")))
    {
        m_dbServiceFactory->ClearDatabase ();
        this->Input (m_dbServiceFactory);

        // 节点固定约束
        SG::DataStructure::FEM::SPCData spc;
        spc.m_sId = 1;
        spc.m_g   = 1;
        spc.m_c   = DofSet2Int ({ DOFDirections::DOF_Ux, DOFDirections::DOF_Uy });
        spc.m_d   = 0;
        m_dbServiceFactory->get<SPCService> ()->Add (spc);
        spc.m_g = 7;
        spc.m_c = DofSet2Int ({ DOFDirections::DOF_Uy });
        spc.m_d = 0;
        m_dbServiceFactory->get<SPCService> ()->Add (spc);
        // 平面桁架，约束面外唯一自由度
        for (int i = 1; i <= 7; i++)
        {
            spc.m_g = i;
            spc.m_c = DofSet2Int ({ DOFDirections::DOF_Uz });
            spc.m_d = 0;
            m_dbServiceFactory->get<SPCService> ()->Add (spc);
        };

        // 加入载荷向量
        {
            SG::DataStructure::FEM::FORCEData force;
            force.m_sId         = 1;
            force.m_coordSysmId = 0;
            force.m_nodeId      = 3;
            force.m_load[0]     = 0.0;
            force.m_load[1]     = -210.0;
            force.m_factor      = 1000.0;
            m_dbServiceFactory->get<MOMENTService> ()->Add (force);

            force.m_sId         = 1;
            force.m_coordSysmId = 0;
            force.m_nodeId      = 5;
            force.m_load[0]     = 0.0;
            force.m_load[1]     = -280.0;
            force.m_factor      = 1000.0;
            m_dbServiceFactory->get<MOMENTService> ()->Add (force);
        }

        {
            SubCase subCase;
            subCase.m_id   = 1;
            subCase.m_spc  = 1;
            subCase.m_load = 1;
            m_dbServiceFactory->get<SubCaseService> ()->Add (subCase);
        }
    }

    /// @brief 写入模型数据
    void               Input (const DBServiceFactorySP m_dbServiceFactory);
    DBServiceFactorySP GetModel ()
    {
        return m_dbServiceFactory;
    }

  private:
    DBServiceFactorySP m_dbServiceFactory;
};

inline void Link_ElevenEleRigid_Frame::Input (DBServiceFactorySP m_dbServiceFactory)
{
    // 节点写入
    NodeData node;
    node.m_id       = 1;
    node.m_defCoord = 0;
    node.m_x[0]     = 0.0;
    node.m_x[1]     = 0.0;
    node.m_x[2]     = 0.0;
    m_dbServiceFactory->get<INodeService> ()->Add (node);
    node.m_id       = 2;
    node.m_defCoord = 0;
    node.m_x[0]     = 1.8;
    node.m_x[1]     = 3.118;
    node.m_x[2]     = 0.0;
    m_dbServiceFactory->get<INodeService> ()->Add (node);
    node.m_id       = 3;
    node.m_defCoord = 0;
    node.m_x[0]     = 3.6;
    node.m_x[1]     = 0.0;
    node.m_x[2]     = 0.0;
    m_dbServiceFactory->get<INodeService> ()->Add (node);
    node.m_id       = 4;
    node.m_defCoord = 0;
    node.m_x[0]     = 5.4;
    node.m_x[1]     = 3.118;
    node.m_x[2]     = 0.0;
    m_dbServiceFactory->get<INodeService> ()->Add (node);
    node.m_id       = 5;
    node.m_defCoord = 0;
    node.m_x[0]     = 7.2;
    node.m_x[1]     = 0.0;
    node.m_x[2]     = 0.0;
    m_dbServiceFactory->get<INodeService> ()->Add (node);
    node.m_id       = 6;
    node.m_defCoord = 0;
    node.m_x[0]     = 9.0;
    node.m_x[1]     = 3.118;
    node.m_x[2]     = 0.0;
    m_dbServiceFactory->get<INodeService> ()->Add (node);
    node.m_id       = 7;
    node.m_defCoord = 0;
    node.m_x[0]     = 10.8;
    node.m_x[1]     = 0.0;
    node.m_x[2]     = 0.0;
    m_dbServiceFactory->get<INodeService> ()->Add (node);

    // 材料写入
    SG::DataStructure::Material::IsotropicMaterial material;
    ;
    material.m_id = 1;
    material.m_E  = 2.10e5;
    material.m_nu = 0.3;
    material.m_G  = material.m_E / 2.0 * (1.0 + material.m_nu);
    m_dbServiceFactory->get<IsotropicMaterialService> ()->Add (material);

    // 截面属性写入
    SG::DataStructure::FEM::PRODData prod;
    prod.m_id            = 1;
    prod.m_mId           = 1;
    prod.m_area          = 0.3205e-2;
    prod.m_torsionFactor = 0.0;
    m_dbServiceFactory->get<PRODService> ()->Add (prod);

    // 单元写入
    SG::DataStructure::FEM::CRODData rodEle;
    rodEle.m_id   = 1;
    rodEle.m_pId  = 1;
    rodEle.m_g[0] = 1;
    rodEle.m_g[1] = 2;
    m_dbServiceFactory->get<CRODService> ()->Add (rodEle);
    rodEle.m_id   = 2;
    rodEle.m_pId  = 1;
    rodEle.m_g[0] = 1;
    rodEle.m_g[1] = 3;
    m_dbServiceFactory->get<CRODService> ()->Add (rodEle);
    rodEle.m_id   = 3;
    rodEle.m_pId  = 1;
    rodEle.m_g[0] = 2;
    rodEle.m_g[1] = 3;
    m_dbServiceFactory->get<CRODService> ()->Add (rodEle);
    rodEle.m_id   = 4;
    rodEle.m_pId  = 1;
    rodEle.m_g[0] = 3;
    rodEle.m_g[1] = 4;
    m_dbServiceFactory->get<CRODService> ()->Add (rodEle);
    rodEle.m_id   = 5;
    rodEle.m_pId  = 1;
    rodEle.m_g[0] = 3;
    rodEle.m_g[1] = 5;
    m_dbServiceFactory->get<CRODService> ()->Add (rodEle);
    rodEle.m_id   = 6;
    rodEle.m_pId  = 1;
    rodEle.m_g[0] = 4;
    rodEle.m_g[1] = 5;
    m_dbServiceFactory->get<CRODService> ()->Add (rodEle);
    rodEle.m_id   = 7;
    rodEle.m_pId  = 1;
    rodEle.m_g[0] = 5;
    rodEle.m_g[1] = 6;
    m_dbServiceFactory->get<CRODService> ()->Add (rodEle);
    rodEle.m_id   = 8;
    rodEle.m_pId  = 1;
    rodEle.m_g[0] = 5;
    rodEle.m_g[1] = 7;
    m_dbServiceFactory->get<CRODService> ()->Add (rodEle);
    rodEle.m_id   = 9;
    rodEle.m_pId  = 1;
    rodEle.m_g[0] = 6;
    rodEle.m_g[1] = 7;
    m_dbServiceFactory->get<CRODService> ()->Add (rodEle);
    rodEle.m_id   = 10;
    rodEle.m_pId  = 1;
    rodEle.m_g[0] = 2;
    rodEle.m_g[1] = 4;
    m_dbServiceFactory->get<CRODService> ()->Add (rodEle);
    rodEle.m_id   = 11;
    rodEle.m_pId  = 1;
    rodEle.m_g[0] = 4;
    rodEle.m_g[1] = 6;
    m_dbServiceFactory->get<CRODService> ()->Add (rodEle);
}